package com.example.demo3;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 - **业务一：**
 - 需要你解析上面的字符串，获取里面的用户数据，并封装到Sutdent对象中
 - 多个Student对象在添加到List<Student> 集合中
 - 注意：
 - 字符串中的规则如下，多个用户用 # 拼接，用户的信息之间用 , 拼接,多个景点是用-拼接的。
 - 其中用户的id和选择时间是需要进行类型转换的，其中id需要将String转成Long，选择时间需要将String转成LocalDateTime。
 - **业务二：**

 - 遍历上面获取的List<Student> 集合，统计里面每个景点选择的次数，并输出 景点名称和选择的次数。
 **业务三：
 * 请用程序计算出哪个景点想去的人数最多，以及哪些人没有选择这个最多人想去的景点。
 */
public class Test3 {
    public static void main(String[] args) {
        String info = "10001,张无忌,男,2023-07-22 11:11:12,东湖-黄鹤楼#10002,赵敏,女,2023-07-22 09:11:21," +
                "黄鹤楼-归元禅寺#10003,周芷若,女,2023-07-22 04:11:21,木兰文化区-东湖#10004," +
                "小昭,女,2023-07-22 08:11:21,东湖#10005,灭绝,女,2023-07-22 17:11:21,归元禅寺";
        // 1.把这个info信息转成List<Student>对象
        List<Student> students = parseStudents(info); // 编写一个方法解析字符串返回一个List<Student>集合
        // students.forEach(System.out::println);

        // 遍历上面获取的List<Student> 集合，统计里面每个景点选择的次数，并输出 景点名称和选择的次数
        Map<String, Integer> map = parseSelectAddress(students);

        // 请用程序计算出哪个景点想去的人数最多，以及哪些人没有选择这个最多人想去的景点。
        String maxAddress = getMaxAddress(map);
        System.out.println("最多人想去的景点：" + maxAddress);

        // 打印那些人没有选择这个景点
        printNotSelectAddress(students, maxAddress);
    }

    /**
     * 打印那些人没有选择这个景点
     * @param students 学生对象集合
     * @param maxAddress 最多人想去的景点名称
     */
    private static void printNotSelectAddress(List<Student> students, String maxAddress) {
        // 使用stream流遍历集合，过滤出没有选择这个景点的人，并打印出来
        students.stream().filter(student -> !student.getAddress().contains(maxAddress))
                .forEach(student -> System.out.println("没有选择" + maxAddress + "的：" + student.getName()));
    }

    /**
     * 获取最多人想去的景点名称
     * @param map 景点和选择的次数
     * @return 最多人想去的景点名称
     */
    private static String getMaxAddress(Map<String, Integer> map) {
        // 使用stream流遍历map集合，获取到最大的键值对，并返回对应的键
        // .get()获取到键值对的值 .getKey()获取到键
        return map.entrySet().stream().max((o1, o2) -> o1.getValue() - o2.getValue()).get().getKey();
    }

    /**
     * 统计每个景点选择的次数
     * @param students 学校对象集合
     */
    public static Map<String, Integer> parseSelectAddress(List<Student> students) {
        // 1.创建一个Map集合，key是景点名称，value是选择的次数
        Map<String, Integer> map = new HashMap<>();
        // 2.遍历List<Student>集合
        for (Student student : students) {
            // 3.获取每个学生选择的景点地址
            String address = student.getAddress();
            // 4.把景点地址按照 - 拆分
            String[] split = address.split("-");
            // 5.遍历每个景点
            for (String s : split) {
                // 6.判断这个景点是否已经存在，如果存在，则次数+1，如果不存在，则次数为1
                if (map.containsKey(s)) {
                    // 说明已经存在了
                    map.put(s, map.get(s) + 1);
                } else {
                    // 说明该景点是第一次出现
                    map.put(s, 1);
                }
            }
        }

        // 遍历输出map集合
        // 遍历方式1 - 键值对
        // for (Map.Entry<String, Integer> entry : map.entrySet()) {
        //    System.out.println("景点名称：" + entry.getKey() + " ，选择了几次： " + entry.getValue());
        // }

        // 遍历方式2 - 键找值
        // Set<String> keys = map.keySet(); // 获取所有的键
        // for (String key : keys) {
        // 根据键去找对应的值
        //    System.out.println("景点名称：" + key + " ，选择了几次： " + map.get(key));
        // }

        // 遍历方式 3 - Lambda
        // map.forEach(new BiConsumer<String, Integer>() {
        //    @Override
        //    public void accept(String address, Integer value) {
        //        System.out.println("景点名称：" + address + " ，选择了几次： " + value);
        //    }
        // });

        // 使用Lambda简化
        map.forEach((k, v) -> System.out.println("景点名称: " + k + " ,选择了几次： " + v));

        // 返回map集合
        return map;
    }

    /**
     * 解析字符串，返回一个List<Student>集合
     * @param info 字符串
     * @return 学生对象集合
     */
    private static List<Student> parseStudents(String info) {
        // 1.把字符串按照#拆分
        String[] studentsInfo = info.split("#");
        // 2.创建一个集合存储学生信息
        List<Student> list = new ArrayList<>();
        // 日期格式化对象
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 3.遍历这个数组
        for (String studentInfo : studentsInfo) {
            // 4.把字符串按照,拆分
            String[] split = studentInfo.split(",");
            // 把日期解析成LocalDateTime对象
            String time = split[3];
            LocalDateTime localDateTime = LocalDateTime.parse(time, dtf);
            // 5.把字符串数组转成对象
            Student student = new Student(Long.parseLong(split[0]), split[1], split[2], localDateTime,
                    split[4]);
            // 6.把对象添加到集合中
            list.add(student);
        }
        // 7.返回集合
        return list;
    }
}


